package org.example.sample1.config;

import java.util.EnumSet;
import org.example.sample1.StateEnums.BeanAEvents;
import org.example.sample1.StateEnums.BeanAStates;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.statemachine.config.EnableStateMachine;
import org.springframework.statemachine.config.EnumStateMachineConfigurerAdapter;
import org.springframework.statemachine.config.builders.StateMachineConfigurationConfigurer;
import org.springframework.statemachine.config.builders.StateMachineStateConfigurer;
import org.springframework.statemachine.config.builders.StateMachineTransitionConfigurer;
import org.springframework.statemachine.listener.StateMachineListener;
import org.springframework.statemachine.listener.StateMachineListenerAdapter;
import org.springframework.statemachine.state.State;

@Configuration
@EnableStateMachine
public class StateMachineConfig extends EnumStateMachineConfigurerAdapter<BeanAStates, BeanAEvents> {

    @Override
    public void configure(StateMachineConfigurationConfigurer<BeanAStates, BeanAEvents> config)
            throws Exception {
        config.withConfiguration().autoStartup(true).listener(listener());
    }

    @Override
    public void configure(StateMachineStateConfigurer<BeanAStates, BeanAEvents> states) throws Exception {
        states.withStates().initial(BeanAStates.S0).states(EnumSet.allOf(BeanAStates.class));
    }

    @Override
    public void configure(StateMachineTransitionConfigurer<BeanAStates, BeanAEvents> transitions)
            throws Exception {
        transitions.withExternal().source(BeanAStates.S0).target(BeanAStates.S1).event(BeanAEvents.E1).and()
                .withExternal().source(BeanAStates.S1).target(BeanAStates.S2).event(BeanAEvents.E2);
    }

    @Bean
    public StateMachineListener<BeanAStates, BeanAEvents> listener() {
        return new StateMachineListenerAdapter<BeanAStates, BeanAEvents>() {
            @Override
            public void stateChanged(State<BeanAStates, BeanAEvents> from, State<BeanAStates, BeanAEvents> to) {
                System.out.println("State change to " + to.getId());
            }
        };
    }
}
